using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Agriculture.Api.Read.Application.Command;
using Agriculture.Domain;
using Dapper;
using MediatR;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using MySql.Data.MySqlClient;

namespace Agriculture.Api.Read.Application.Handler
{
    /// <summary>
    /// 用户登录命令处理器
    /// </summary>
    public class UserLoginCommandHandler : IRequestHandler<UserLoginCommand, UserLoginResult>
    {
        /// <summary>
        /// 配置接口
        /// </summary>
        private readonly IConfiguration _configuration;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="configuration">配置接口</param>
        public UserLoginCommandHandler(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        /// <summary>
        /// 处理用户登录请求
        /// </summary>
        /// <param name="request">登录命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>登录结果，包含用户信息和JWT令牌</returns>
        public async Task<UserLoginResult> Handle(UserLoginCommand request, CancellationToken cancellationToken)
        {
            // 获取数据库连接字符串
            string connectionString = _configuration.GetConnectionString("DefaultConnection");
            
            // 将密码进行MD5加密以便与数据库中存储的加密密码进行比对
            string encryptedPassword = EncryptPasswordMD5(request.Password);

            using (var connection = new MySqlConnection(connectionString))
            {
                // 查询用户信息，支持使用用户名或手机号登录，移除不存在的RealName和Avatar字段
                var userSql = @"
                    SELECT u.Id, u.UserName, u.Phone, u.Password, u.Sex, u.Age
                    FROM usermodel u
                    WHERE (u.UserName = @Account OR u.Phone = @Account) AND u.IsDeleted = 0
                    LIMIT 1";

                var user = await connection.QueryFirstOrDefaultAsync<dynamic>(userSql, new { Account = request.Account });

                // 用户不存在或密码错误
                if (user == null || user.Password != encryptedPassword)
                {
                    return null;
                }

                // 生成JWT令牌
                var jwtSettings = _configuration.GetSection("JwtSettings");
                var tokenHandler = new JwtSecurityTokenHandler();
                var key = Encoding.ASCII.GetBytes(jwtSettings["SigningKey"]);
                var tokenExpireMinutes = int.Parse(jwtSettings["AccessTokenExpirationMinutes"]);
                var tokenExpireTime = DateTime.Now.AddMinutes(tokenExpireMinutes);

                // 配置JWT令牌描述
                var tokenDescriptor = new SecurityTokenDescriptor
                {
                    // 设置令牌中包含的声明，使用默认角色"User"
                    Subject = new ClaimsIdentity(new[]
                    {
                        new Claim(ClaimTypes.Name, user.UserName),
                        new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
                        new Claim(ClaimTypes.Role, "User")  // 使用默认角色
                    }),
                    // 设置令牌过期时间
                    Expires = tokenExpireTime,
                    // 设置令牌的签名凭据
                    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
                    // 设置令牌的颁发者
                    Issuer = jwtSettings["Issuer"],
                    // 设置令牌的受众
                    Audience = jwtSettings["Audience"]
                };

                // 创建JWT令牌
                var token = tokenHandler.CreateToken(tokenDescriptor);

                // 构建并返回登录结果
                return new UserLoginResult
                {
                    UserId = user.Id,
                    UserName = user.UserName,
                    RealName = user.UserName, // 使用UserName代替不存在的RealName
                    Phone = user.Phone,
                    Avatar = string.Empty, // Avatar不存在，设置为空字符串
                    Role = "User",  // 使用默认角色
                    Token = tokenHandler.WriteToken(token),
                    TokenExpireTime = tokenExpireTime
                };
            }
        }

        /// <summary>
        /// 使用MD5加密密码
        /// </summary>
        /// <param name="password">原始密码</param>
        /// <returns>加密后的密码</returns>
        private string EncryptPasswordMD5(string password)
        {
            using (var md5 = MD5.Create())
            {
                // 将密码字符串转换为字节数组
                var inputBytes = Encoding.UTF8.GetBytes(password);
                // 计算MD5哈希值
                var hashBytes = md5.ComputeHash(inputBytes);

                // 将字节数组转换为十六进制字符串
                var sb = new StringBuilder();
                for (int i = 0; i < hashBytes.Length; i++)
                {
                    sb.Append(hashBytes[i].ToString("x2"));
                }
                return sb.ToString();
            }
        }
    }
} 